package factory;

import config.XmlReader;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import proxy.ProxyFactory;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author wsz
 * @date 2021/10/13 9:25
 **/
public class DefaultBeanFactory implements BeanFactory {

    // bean存储的容器
    private Map<String, Object> beanMap = new HashMap<>();
    // 内部自动加载的文件
    private final static String INIT_XML = "base.xml";

    // 代理工厂
    private ProxyFactory proxyFactory;

    public DefaultBeanFactory () {
        this("beans.xml");
    }

    public DefaultBeanFactory (String path) {
        try {
            // 先加载默认的配置
            xmlReader(INIT_XML);
            // 加载自定义的配置
            xmlReader(path);
            // xml加载后，直接获取代理工厂
            proxyFactory = (ProxyFactory) beanMap.get("proxyFactory");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 返回代理后的对象，可以进行事务管控
     * @param beanName
     * @return
     */
    @Override
    public Object getBean(String beanName) {
        Object bean = beanMap.get(beanName);
        if (bean == null) {
            throw new RuntimeException("cannot find bean by name:" + beanName);
        }
        return proxyFactory.getProxy(bean);
    }

    @Override
    public void addBean(String beanName, Object bean) {
        beanMap.put(beanName, bean);
    }

    private void xmlReader(String path) throws Exception {

        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(XmlReader.read(path));

        Element rootElement = document.getRootElement();

        List<Element> beanElList = rootElement.selectNodes("//bean");
        beanElList.forEach(beanEl -> {
            String id = beanEl.attributeValue("id");
            String clazz = beanEl.attributeValue("class");

            try {
                // 未注入property
                beanMap.put(id, Class.forName(clazz).newInstance());
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        List<Element> propertyElList = rootElement.selectNodes("//property");
        propertyElList.forEach(propertyEl -> {
            String name = propertyEl.attributeValue("name");
            String ref = propertyEl.attributeValue("ref");

            String parentId = propertyEl.getParent().attributeValue("id");
            Object parent = beanMap.get(parentId);
            Method[] methods = parent.getClass().getMethods();
            for (int i = 0; i < methods.length; i++) {
                Method method = methods[i];
                // set注入
                if (("set"+ name).equalsIgnoreCase(method.getName())) {
                    Object refObj = beanMap.get(ref);
                    try {
                        method.invoke(parent, refObj);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                // 成员变量赋值
            }
            // 完整bean
            beanMap.put(parentId, parent);
        });
    }

}
